package com.demo.config.sharding.algorithm;

/**
 * @Author: shenyang
 * @CreateTime: 2022-11-22  10:00
 * @Description: TODO
 * @Version: 1.0
 */

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;

import com.google.common.collect.Range;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ModuloShardingDatabaseDateYearAlgorithm implements StandardShardingAlgorithm<String>{
    private int ModedID=5;
    private static final String DataBase_NAME = "ds_";

    //获得日期字段中年份数字，如果年份<1995，返回1995
    private int getYearFromString(String value) throws ParseException {
        int nYear=-1;
        try {
            if(null==value||""==value||value.length()<4) {
                Date date = new Date();
                return date.getYear();
            }
            else {
                try {
                    nYear=Integer.valueOf(value.substring(0, 4));
                }
                catch(Exception e) {
                    Date date = new Date();
                    return date.getYear();
                }
            }
            if(nYear<1995)
                nYear=1995;
        }
        catch(Exception e) {
            Date date = new Date();
            return date.getYear();
        }
        return nYear;
    }


    /*
     *databaseNamescollection:配置文件中定义的数据库名称集合
     *shardingValue：insert,select,update,delate时，Create_Date字段值
     *函数返回值：返回函数值shardingValue经过取余计算后对于的数据库名称。比如 1995%4 =3，返回数据库名称是ds_3
     */
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<String> shardingValue) {
        if (shardingValue != null) {
            String value = shardingValue.getValue();//获取传递的字段值

            int nYear=-1;
            try {
                nYear = getYearFromString(value);//获取年份

            } catch (ParseException e) {

                e.printStackTrace();
            }
//对年份取余，将余数跟数据库前缀组合成数据库名称，
//检查这个名称是否在配置文件数据库集合中，如果存在返回数据库名称
            for (String each : availableTargetNames) {
                if (each.equals(DataBase_NAME + String.valueOf(nYear%4))) {
                    return each;
                }
            }
            throw new  UnsupportedOperationException("content_channel没有匹配到可用数据库节点");
        } else {
            throw new UnsupportedOperationException("分片列为空");
        }
    }

    /*
     *databaseNamescollection:配置文件中定义的数据库名称集合
     *rangeShardingValue：insert,select,update,delate时，Create_Date 范围查询字段值。比如 between 2015-01-01 and 2021-01-01，存储的就是 2015-01-01和2021-01-01
     *函数返回值：返回函数值rangeShardingValue经过取余计算后对于的数据库名称。比如 between 2015-01-01 and 2021-01-01 ，根据这时间段年份，得到返回的集合是ds_0,ds_1,ds_2,ds_3
     */

    @Override
    public Collection<String> doSharding(Collection<String> databaseNamescollection, RangeShardingValue<String> rangeShardingValue) {

        Collection<String> collect = new ArrayList<>();
        if (rangeShardingValue != null) {
            Range<String> valueRange = rangeShardingValue.getValueRange();//获得范围区间值
            String slowerEndpointDate = String.valueOf(valueRange.hasLowerBound()?valueRange.lowerEndpoint():"");       //获得返回区间值下限
            String supperEndpointDate = String.valueOf(valueRange.hasUpperBound()?valueRange.upperEndpoint():"");//获得范围区间值上限


            int nStartYear =-1;
            int nEndYear=-1;
            try {

                nStartYear = getYearFromString(slowerEndpointDate) ;//获得下限年份
                nEndYear = getYearFromString(supperEndpointDate) ;//获得上限年份

                if(nStartYear==-1&&nEndYear!=-1) {//下限年份为空时，上限不为空时，下限=上限-5
                    nStartYear=nEndYear-ModedID;
                } else if(nStartYear!=-1&&nEndYear==-1) {//下限不为空，上限为空，上限=下限+5
                    nEndYear=nStartYear+ModedID;
                }
            } catch (ParseException e) {

                e.printStackTrace();
            }

            //根据上下限范围，循环取值判断对应的数据库名称，返回数据库名称集合
            for (String each : databaseNamescollection) {
                for(int i=nStartYear;i<=nEndYear;i++) {
                    if (each.equals(DataBase_NAME + String.valueOf(i%4))) {
                        if(!collect.contains(each)) {
                            collect.add(each);
                        }
                    }
                }
            }
            return collect;


        }else {
            throw new UnsupportedOperationException("分片列为空");
        }

    }

    @Override
    public void init() {

    }

    @Override
    public String getType() {
        return null;
    }

}
